﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEditor.Experimental.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEngine;
//using WebSocketSharp;

public class AutoFind : UnityEditor.Editor
{
    private static List<string> strList = new List<string>();
    private static List<string> strList2 = new List<string>();
    private static GameObject selectingObj;
    private static readonly string autoFindDir = "Assets/AssetPackage/Scripts/AutoFind/";//"HotFix/UI/AutoFind/"
    private static Dictionary<string, string> _dic = new Dictionary<string, string>()
    {
        {"@go_", "GameObject"},
        {"@tran_", "Transform" },
        {"@rect_", "RectTransform" },

        {"@img_", "Image"},
        {"@rawimg_", "RawImage" },
        {"@btn_", "Button"},
        {"@toggle_", "Toggle" },

        {"@txt_", "Text"},
        {"@input_", "InputField"},
        {"@tmp_", "TextMeshProUGUI"},
        {"@tmpinput_", "TMP_InputField"},

        {"@slider_", "Slider" },
        {"@drop_", "Dropdown" },
        {"@cg_", "CanvasGroup" },
        {"@es_", "EnhancedScroller" },
        {"@sb_", "Scrollbar" },
        {"@sr_", "ScrollRect" },

        {"@spine_", "SkeletonGraphic" },
    };
    [MenuItem("ZTools/单个UI组件绑定 %F7")]
    static void Test()
    {
        strList.Clear();
        strList2.Clear();
        selectingObj = Selection.activeGameObject;
        bool isVariant = false;
        LinkedList<string> indexList = new LinkedList<string>();
        for (var i = 0; i < selectingObj.transform.childCount; i++)
        {
            var child = selectingObj.transform.GetChild(i);
            indexList.AddLast(child.name);
            Walk(child, "transform", indexList);
            if (PrefabUtility.IsPartOfPrefabInstance(child))
            {
                isVariant = true;
            }
        }
        
        Gen(isVariant);
    }
 
    static List<string> GetAllPrefabs(string directory)
    {
        if (string.IsNullOrEmpty(directory) || !directory.StartsWith("Assets"))
            throw new ArgumentException("folderPath");

        string[] subFolders = Directory.GetDirectories(directory);
        string[] guids = null;
        List<string> assetPaths = new List<string>();
        int i = 0, iMax = 0;
        foreach (var folder in subFolders)
        {
            guids = AssetDatabase.FindAssets("t:Prefab", new string[] { folder });
            for (i = 0, iMax = guids.Length; i < iMax; ++i)
            {
                assetPaths.Add(AssetDatabase.GUIDToAssetPath(guids[i]));
            }
        }

        return assetPaths;
    }


    [MenuItem("ZTools/所有UI组件绑定")]
    public static void GenAll()
    {
        //找到所有Project下GameObject
        string[] guids = AssetDatabase.FindAssets($"t:{"GameObject"}");

        var folder = "Assets/AssetPackage/UI/";

        // 对每个GameObject进行操作
        foreach (var x in GetAllPrefabs(folder))
        {
            //加载对象
            selectingObj = AssetDatabase.LoadAssetAtPath<GameObject>(x);
            strList.Clear();
            strList2.Clear();
            LinkedList<string> indexList = new LinkedList<string>();
            for (var i = 0; i < selectingObj.transform.childCount; i++)
            {
                var child = selectingObj.transform.GetChild(i);
                indexList.AddLast(child.name);
                Walk(child, "transform", indexList);
            }

            Gen();
        }
    }

    static void Walk(Transform go, string parent, LinkedList<string> indexList)
    {
        var a = "";
        var b = "";
        var n = go.name.Substring(1);

        bool find = false;
        LinkedList<string> oldList = indexList;
        foreach (var kv in _dic)
        {
            if (go.name.StartsWith(kv.Key))
            {
                a = $"public {kv.Value} {n};";
                string c = GenGetChild(indexList);
                if (kv.Key == "@go_")
                {
                    b = $"{n} = {parent}{c}.gameObject";
                    n = $"{n}.transform";
                }
                else if (kv.Key == "@tran_")
                {
                    b = $"{n} = {parent}{c}";
                }
                else
                {
                    b = $"{n} = {parent}{c}.GetComponent<{kv.Value}>()";
                    n = $"{n}.transform";
                }
                find = true;
                break;
            }
        }

        if (find)
        {
            // 如果找到了，就把 parent 更新成自己，并重新创建一个 indexList
            parent = n;
            indexList = new LinkedList<string>();
        }

        if (a != "")
        {
            //继承的部分无需生成(这样得保证继承部分不变，且必须实现继承)
            if (!PrefabUtility.IsPartOfPrefabInstance(go))
            {
                //Debug.Log($"{go.name} 是预制体，跳过孩子生成");
                strList.Add(a);
                strList2.Add(b);
            }
        }

        //if (PrefabUtility.IsPartOfPrefabInstance(go))
        //{
        //    Debug.Log($"{go.name} 是预制体，跳过孩子生成");
        //}
        //else
        //{
        //    for (var i = 0; i < go.transform.childCount; i++)
        //    {
        //        var child = go.transform.GetChild(i);
        //        indexList.AddLast(child.name);
        //        Walk(child, parent, indexList);
        //    }
        //}
        for (var i = 0; i < go.transform.childCount; i++)
        {
            var child = go.transform.GetChild(i);
            indexList.AddLast(child.name);
            Walk(child, parent, indexList);
        }
        // 将自己的序号弹出
        oldList.RemoveLast();
    }
    private static string GenGetChild(LinkedList<string> queue)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(".Find(\"");

        int count = queue.Count;
        int idx = 0;
        foreach (var index in queue)
        {
            idx++;
            builder.Append(index);
            if (idx < count) builder.Append("/");
        }

        builder.Append("\")");

        return builder.ToString();
    }
    private static string GenText(string clsName, string clsName2, string autoFindFields, string autoFindValue, string isView)
    {
        var p = AssetDatabase.GetAssetPath(selectingObj);
        if (string.IsNullOrEmpty(p))
        {
            // 不在project 下  在hierarchy下的情况
            p = PrefabStageUtility.GetCurrentPrefabStage()?.prefabAssetPath;
        }
        // 去掉后缀
        p = p.Substring(0, p.Length - 7);


        return $@"//本文件自动生成
//using HotFix.UI;
using UnityEngine;
using UnityEngine.UI;
// using TMPro;
// using EnhancedUI.EnhancedScroller;
// using Spine.Unity;


public partial class {clsName2}
{{
    {autoFindFields}
    public string ResName => ""{p}"";
    public void InitFindChildren()
    {{
        {autoFindValue}
    }}
}}

";
    }

    private static void GenFile(string clsName, string clsName2, string autoFindFields, string autoFindValue, string isView)
    {
        var fileName = autoFindDir + clsName + ".cs";
        File.WriteAllText(fileName, GenText(clsName, clsName2, autoFindFields, autoFindValue, isView));
        Debug.Log($"已生成 {fileName} 至 {autoFindDir}");
    }

    static void Gen(bool isvariant = false)
    {
        if (!Directory.Exists(autoFindDir)) Directory.CreateDirectory(autoFindDir);
        //Directory.SetCurrentDirectory(autoFindDir);
        try
        {
            var implFileFormat = "UIView{0}";
            if (selectingObj.name.StartsWith("@") || selectingObj.name.Contains("Enviroment"))
            {
                Debug.LogError("你可能选错对象了...");
                return;
            }
            string isView = string.Empty;
            if (selectingObj.name.Contains("View") || selectingObj.name.Contains("Panel") || selectingObj.name.Contains("Item"))
            {
                Debug.Log("名字含有 View 和 Panel 的界面，默认为 UIBase");
                isView = "override";
            }
            var a = selectingObj.name.Replace("View", "");
            var clsName = string.Format(implFileFormat, a);
            var clsName2 = $"UI{a}";
            var fileName = string.Format(implFileFormat, a) + ".cs";
            var aa = strList.Aggregate("", (current, x) => current + x + "\n        ");
            var bb = strList2.Aggregate("", (current, x) => current + x + ";\n            ");
            if(isvariant)
                bb = bb.Insert(0, "base.InitFindChildren();" + "\n");
            GenFile(clsName, clsName2, aa, bb, isView);
        }
        finally
        {
            //Directory.SetCurrentDirectory("../../../");
        }
    }
}